import socket from '@ohos.net.socket';
import worker from '@ohos.worker';
import wifiManager from '@ohos.wifiManager';
import { GyroscopeControl, Info } from '../common/RemoteControl/GyroscopeControl';
import { FlightGearDataEncoder } from '../common/RemoteControl/Impl/FlightGearDataEncoder';
import { ipToStr } from '../common/NetWork/AddressUtil';

let localIP = "";
let localPort = 9999;
let addr: Address = null;
let udpRecv = socket.constructUDPSocketInstance();
let bind: Boolean = false;

const workerPort = worker.workerPort;

let gyscope: GyroscopeControl | null = null;

let encoder = new FlightGearDataEncoder();

workerPort.onmessage = (event) => {
  if (event.data == "start") {
    if (gyscope == null) {
      gyscope = new GyroscopeControl(1e5);
      gyscope.setCallback((data) => {
        let str = encoder.encode(data);
        if (addr != null) {
          udpRecv.send({ address: { address: addr.ip, port: addr.port, family: 1 }, data: str });
        }
        workerPort.postMessage(data.toObject());
      });
    }
  } else if (event.data == "stop") {
    if (gyscope != null) {
      gyscope.close();
      gyscope = null;
    }
  } else if (event.data instanceof Object) {
    let info = Info.fromObject(event.data);
    if (info != null) {
      if (gyscope != null) {
        gyscope.close();
      }
      let str = encoder.encode(info);
      udpRecv.send({ address: { address: addr.ip, port: addr.port, family: 1 }, data: str });
      workerPort.postMessage(info.toObject());
    }
  }
}


class Address {
  ip: string;
  port: number;
}

export class UdpUtils {
  constructor() {
    if (!bind) {
      let ipNum = wifiManager.getIpInfo().ipAddress;
      localIP = ipToStr(ipNum);
      this.bind();
      bind = true;
      this.recvData((data) => {
        workerPort.postMessage(data);
      })
    }
  }

  public bind() {
    let promise = udpRecv.bind({ address: localIP, port: localPort, family: 1 });
    promise.then(() => {
      udpRecv.setExtraOptions({ broadcast: true });
      console.log('bind success');
    }).catch(err => {
      console.log('bind fail');
    });
  }

  public recvData(callback: (data: Map<string, number>) => void) {
    udpRecv.on('message', value => { // console.log("on message, message:" + JSON.stringify(value));
      //value中的message才是发送过来的数据，并且是ArrayBuffer类型，需要先转成string类型
      // let recvData = this.arrayBufferToString(value.message);
      // let recvData = this.decode(value.message);
      // callback(recvData);
      if (addr == null) {
        addr = new Address();
        addr.ip = value.remoteInfo.address;
        addr.port = 10000;
      }
      let map = this.decode(value.message);
      workerPort.postMessage(map); // workerPort.postMessage({ type: "data", data: map });
    });
  }


  public send(sendDataString: string | ArrayBuffer) {
    if (addr != null) {
      let promise = udpRecv.send({ data: sendDataString, address: { address: addr.ip, port: addr.port, family: 1 } });
      promise.then(() => {
        console.log('send success');
      }).catch(err => {
        console.log('send fail' + err);
      });
    }
  }


  isJsonString(str) {
    if (typeof str == 'string') {
      try {
        var obj = JSON.parse(str);
        if (typeof obj == 'object' && obj) {
          return true;
        } else {
          return false;
        }
      } catch (e) {
        console.log('error：' + str + '!!!' + e);
        return false;
      }
    }
    console.log('It is not a string!');
    return false;
  }

  arrayBufferToString(buffer): string {
    return String.fromCharCode.apply(null, new Uint8Array(buffer))
  }

  //解码
  decode(buffer: ArrayBuffer): Map<string, number> {
    let str = String.fromCharCode.apply(null, new Uint8Array(buffer))
    let strArr = str.split("\n");
    let recvDataMap = new Map();
    for (let i = 0; i < strArr.length; i++) {
      strArr[i] = strArr[i].trim();
      let num = Number(strArr[i]);
      recvDataMap.set(TYPE_LIST[i], num)
    }
    return recvDataMap;
  }

  public close() {
    udpRecv.close();
    udpRecv = socket.constructUDPSocketInstance();
    bind = false;
  }
}


new UdpUtils();

const TYPE_LIST = ["对地速度", "空速", "向下分速度", "向东分速度", "向北分速度", "升降速度", "指示速度", "真实速度", "俯仰角", "旋转角", "离地高度", "海拔高度", "经度", "纬度", "航向", "航向偏移度", "转弯速率", "滑动程度", "发动机是否运转", "发动机转速", "通讯电源按钮", "通讯音量", "通讯频道", "测距仪开关", "重力加速度",];
